package main

import (
	"fmt"
	"time"
)

/*
select关键字用于处理多个通道操作。它允许在多个通道上进行选择，以执行发送或接收操作。
select语句会阻塞，直到其中一个通道可以进行发送或接收操作。它会按照顺序检查每个通道，直到找到可以进行操作的通道。
如果有多个通道可以进行操作，select`语句会随机选择一个通道进行操作。
select语句可以用于实现并发编程中的多路复用、超时处理、轮询等场景。通过使用select语句，可以在多个通道之间进行非阻塞的选择，从而实现并发控制和资源共享。

select {
case <-channel1:

	// 当channel1接收到数据时执行的代码

case data := <-channel2:

	// 当channel2接收到数据时，将数据赋值给data变量，并执行相应的代码

default:

	// 如果以上通道都没有接收到数据，则执行default代码块
	}
*/
func main() {
	d3_2()
}

func d3_1() {
	fmt.Println("1. tick begin")
	// tick打表器，以固定的节奏执行
	tick := time.Tick(2 * time.Second)
	for i := 0; i < 5; i++ {
		fmt.Println(i, time.Now())
		time.Sleep(3 * time.Second)
		num := <-tick //两次读取tick数据的间隔，至少2s。Sleep 会失效，最多与tick一直
		fmt.Println(i, num)
	}
	fmt.Println("1. tick end")
}

func d3_2() {
	ch := make(chan int)

	tmp := []int{3, 3, 3, 3, 1}

	for i := 0; i < 5; i++ {
		// 随机数字1~5
		//r := rand.Intn(4) + 1
		s := tmp[i]
		fmt.Printf("begin, i=%d, s=%d, time=%v \n", i, s, time.Now())
		go d3_2_write(ch, i, s)

		select {
		case <-time.After(1 * time.Second):
			fmt.Printf("超时, x=3\n")
		case x := <-ch:
			as := []int{x}
			// ch可能有多个数据，就继续读取
			l := len(ch)
			if l > 1 {
				for num := range ch {
					as = append(as, num)
				}
			}
			fmt.Printf("写入数据, x=%d \n", as)
		}
	}

	go func() {
		for num := range ch {
			fmt.Println("还有数据没有消费, ", num)
		}
	}()

}

func d3_2_write(ch chan<- int, n int, s int) {
	// 在 goroutine 中执行
	time.Sleep(time.Duration(s) * time.Second)
	ch <- n
	fmt.Println("goroutine:写入数据, ", n)
}
